package com.xishu.service;

import com.xishu.entity.NameAndId;
import com.xishu.entity.shop.*;
import com.xishu.exception.ResponseStatusException;
import com.xishu.response.VerifyUtil;
import com.xishu.util.DateUtil;
import com.xishu.util.ServletUtil;
import com.xishu.util.Tools;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public class CatalogService implements Tools {
    private static Logger logger = LoggerFactory.getLogger(CatalogService.class);
    private static CatalogService instance = new CatalogService();
    private CommonService commonService = CommonService.getInstance();

    private CatalogService() {
    }

    public static CatalogService getInstance() {
        return instance;
    }

    /**
     * 查询品类
     *
     * @param catalogId
     * @return
     */
    public Catalog findCatalogById(Long catalogId) throws Exception {
        Catalog catalog = new Catalog();
        catalog.setId(catalogId);
        catalog.setEntity(true);
        return CommonService.getInstance().findEntity(catalogId, Catalog.class);
    }

    /**
     * 查询品类
     *
     * @param catalogId
     * @return
     */
    public Optional<Catalog> findCatalog(Long catalogId) {
        Catalog catalog = new Catalog();
        catalog.setId(catalogId);
        catalog.setEntity(true);
        return CommonService.getInstance().searchOneOptional(catalog);
    }

    /**
     * 查询品类，如果列表里面有，直接返回
     *
     * @param catalogId
     * @param catalogList
     * @return
     */
    public Optional<Catalog> findCatalog(Long catalogId, List<Catalog> catalogList) {
        Optional<Catalog> catalogOptional = getList(catalogList).stream().filter(p -> equals(p.getId(), catalogId)).findAny();
        if (catalogOptional.isPresent()) {
            return catalogOptional;
        }

        Optional<Catalog> optionalCatalog = findCatalog(catalogId);
        //不存在，直接返回
        if (!optionalCatalog.isPresent()) {
            return optionalCatalog;
        }

        catalogList.add(optionalCatalog.get());
        return optionalCatalog;
    }

    /**
     * 通过商铺来查询品类
     * 后续加缓存
     *
     * @param shopId
     * @return
     */
    public List<Catalog> findCatalogByShopId(Long shopId) {
        Catalog catalog = new Catalog();
        catalog.setShopId(shopId);
        catalog.setEntity(true);
        return CommonService.getInstance().searchAll(catalog);
    }

    /**
     * 通过名称查询某一个分店下面的分类
     *
     * @param catalogName
     * @return
     */
    public Catalog findCatalogByName(Long shopId, String catalogName) throws ResponseStatusException {
        VerifyUtil.verify(() -> isNotEmpty(catalogName));
        Catalog catalog = new Catalog();
        catalog.setShopId(shopId);
        catalog.setName(catalogName);
        catalog.setEntity(true);
        return CommonService.getInstance().searchOne(catalog);
    }


    /**
     * 将品类的名称映射到其它位置
     *
     * @param catalogId
     */
    public void catalogNameSyncToOthers(Long catalogId) throws Exception {
        VerifyUtil.verify(() -> catalogId != null);
        Catalog catalog = commonService.findEntity(catalogId, Catalog.class);
        CatalogItemMapping catalogItemMapping = new CatalogItemMapping();
        catalogItemMapping.setCatalogId(catalogId);
        List<CatalogItemMapping> itemMappingList = commonService.searchAll(catalogItemMapping);

        for (CatalogItemMapping itemMapping : itemMappingList) {
            itemMapping.setCatalogName(catalog.getName());
            itemMapping.setCatalogName_zh(catalog.getName_zh());
            itemMapping.setCatalogName_en(catalog.getName_en());
            commonService.save(itemMapping);
        }
    }

    /**
     * 重新修改品类的顺序
     *
     * @param catalog
     */
    public void resetCatalogShowOrder(Catalog catalog) throws Exception {
        Catalog catalogInDb = commonService.findEntity(catalog.id, Catalog.class);
        List<Catalog> catalogList = ShopService.getInstance().findCatalog(catalogInDb.getShopId());
        logger.info("item list size is {}", catalogList.size());
        Long catalogShowOrder = catalogInDb.getShowOrder();
        List<Catalog> sameOrderCatalogList = catalogList.stream().filter(p -> equals(p.getShowOrder(), catalogShowOrder) && p.id.longValue() != catalog.id.longValue()).collect(Collectors.toList());
        logger.info("find the same order item list");

        //如果有相同顺序的菜品，那么所有大于等于菜的顺序均加1
        if (isNotEmpty(sameOrderCatalogList)) {
            List<Catalog> modifyItemList = catalogList.stream().filter(p -> getLong(p.getShowOrder()) >= catalogShowOrder && p.id.longValue() != catalog.id.longValue()).collect(Collectors.toList());

            for (Catalog modifyCatalog : modifyItemList) {
                modifyCatalog.setShowOrder(modifyCatalog.getShowOrder() + 1);
                logger.info("will modify item {} show order", modifyCatalog.getId());
                commonService.save(modifyCatalog);
            }
        }
    }

    /**
     * 将品类的名称复制到菜品里面
     *
     * @param catalog
     */
    public void syncToItemName(Catalog catalog) throws Exception {
        logger.info("sync to modify item name");
        Catalog catalogInDb = commonService.findEntity(catalog.getId(), Catalog.class);
        Item itemReq = new Item();
        itemReq.setCatalogId(catalog.getId());
        itemReq.setEntity(true);
        List<Item> itemList = commonService.searchAll(itemReq);
        for (Item item : itemList) {
            item.setCatalogName(catalogInDb.getName());
            item.setCatalogName_en(catalogInDb.getName_en());
            item.setCatalogName_zh(catalogInDb.getName_zh());
            commonService.save(item);
        }
    }

    /**
     * 品类是否在场景的时间范围内
     *
     * @param sceneId
     * @param catalog
     * @return
     */
    public boolean isCatalogInSceneTime(Long sceneId, Catalog catalog) throws Exception {
        if (catalog == null) {
            logger.info("catalog is empty");
            return false;
        }

        if (sceneId == null) {
            logger.info("scene is empty");
            return false;
        }

        Scene scene = SceneService.getInstance().findScene(sceneId);
        Optional<SceneTimeConfig> sceneTimeConfigOptional = SceneService.getInstance().getSceneTimeConfig(scene);

        if (!sceneTimeConfigOptional.isPresent()) {
            logger.info("scene time is not valid");
            return false;
        }

        //有场景，那么看是否跟当前的场景保持一致
        List<NameAndId> sceneList = catalog.getSceneList();
        if (isNotEmpty(sceneList)) {
            return sceneList.stream().map(p -> p.getId()).filter(p -> equals(p, sceneId)).findAny().isPresent();
        } else {
            //两个时间取交集
            List<TimeConfig> timeConfigList = catalog.getTimeConfigList();
            if (isEmpty(timeConfigList)) {
                logger.info("time config list is empty");
                return false;
            }

            SceneTimeConfig sceneTimeConfig = sceneTimeConfigOptional.get();
            TimeConfig timeConfigInScene = SceneService.getInstance().sceneTimeToTimeConfig(sceneTimeConfig);


            return timeConfigList.stream().filter(timeConfig -> DateUtil.hasSameTime(timeConfig, timeConfigInScene)).findAny().isPresent();
        }
    }

    /**
     * 是否可以删除品类
     *
     * @param catalogId
     * @return
     */
    public boolean canDelete(Long catalogId) {
        CatalogItemMapping catalogItemMapping = new CatalogItemMapping();
        catalogItemMapping.setEntity(true);
        catalogItemMapping.setCatalogId(catalogId);
        List<CatalogItemMapping> catalogItemMappingList = commonService.searchAll(catalogItemMapping);

        if (isEmpty(catalogItemMappingList)) {
            logger.info("empty mapping");
            return true;
        }

        return !catalogItemMappingList.stream().filter(mapping -> {
            Long itemId = mapping.getItemId();
            Optional<Item> itemOption = ItemService.getInstance().findItemOption(itemId);
            return itemOption.isPresent();
        }).findAny().isPresent();
    }

    /**
     * 判断品类里面是否还包含有菜品
     *
     * @param catalogId
     * @return
     */
    public boolean catalogContainItem(Long catalogId, Long sceneId) {
        CatalogItemMapping catalogItemMapping = new CatalogItemMapping();
        catalogItemMapping.setEntity(true);
        catalogItemMapping.setCatalogId(catalogId);
        List<CatalogItemMapping> catalogItemMappingList = commonService.searchAll(catalogItemMapping);
        logger.info("mapping {} size is {}", catalogId, catalogItemMappingList.size());
        if (isEmpty(catalogItemMappingList)) {
            return false;
        }

        //再判断每一个菜是否还存在，如果还存在，则存在，如果菜不存在了，有可能是删除菜的时候，映射关系没有删除
        List<Item> itemList = catalogItemMappingList.stream().map(itemMapping -> {
            Long itemId = itemMapping.getItemId();
            Optional<Item> itemOption = ItemService.getInstance().findItemOption(itemId);
            return itemOption;
        }).filter(itemOptional -> itemOptional.isPresent()).map(itemOptional -> itemOptional.get()).filter(item -> getBoolean(item.getOnline())).filter(item -> {
            if (getBoolean(ServletUtil.isCustomerRequest())&&getBoolean(item.getNotShowInC())){
                //c端请求，隐藏不显示的菜
                return false;
            }
            //菜如果配置了场景，那么必须是开启,不区分时价菜，还是套餐，还是普通菜
            else if (isNotEmpty(item.getPriceConfigList())) {
                return item.getPriceConfigList().stream().filter(priceConfig -> getBoolean(priceConfig.getEnable())).filter(priceConfig -> equals(priceConfig.getSceneId(), sceneId)).findAny().isPresent();
            } else if (getBoolean(item.getRealPriceItem())) {
                return true;
            } else {
                //普通菜或者是套餐
                return getDouble(item.getPrice()) > 0;
            }
        }).collect(Collectors.toList());

        List<Long> itemIdList = itemList.stream().map(p -> p.getId()).collect(Collectors.toList());
        logger.info("item list is {}", StringUtils.join(itemIdList, ","));

        return isNotEmpty(itemList);
    }
}
